package com.kili.picture.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kili.picture.context.exception.DataException;
import com.kili.picture.domain.dao.PictureMapper;
import com.kili.picture.domain.entity.Picture;
import com.kili.picture.service.PictureConfigService;
import com.kili.picture.service.PictureService;
import com.kili.picture.tools.OSSClientUtils;
import com.kili.picture.tools.file.FileUtils;
import com.kili.picture.tools.id.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import static com.kili.picture.service.PictureConfigService.getPrefixFromCache;

/**
 * <p>
 * 图片 服务实现类
 * </p>
 *
 * @author Jar
 * @since 2019-04-01
 */
@Service
@Slf4j
public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture> implements PictureService {

    private static final Logger logger = LoggerFactory.getLogger(PictureServiceImpl.class);

    @Value("${file.tempPath}")
    private String tempPath;

    @Value("${file.exceptionPath}")
    private String exceptionPath;

    @Value("${file.host}")
    private String fileHost;

    @Autowired
    private PictureConfigService pictureConfigService;

    private static final String FORMAT = "yyyy/MM/dd/";

    private static final String IMAGE = "image";

    private static final String SLASH = "/";

    @PostConstruct
    private void init() {
        File file = new File(exceptionPath);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    @Override
    public String upload(MultipartFile file, String module) {
        String prefix = getPrefixFromCache(module);
        String id = IdWorker.getIdStr();

        // 文件名
        String fileName = file.getOriginalFilename();
        // 获取扩展名
        StringBuilder path = new StringBuilder().
                append(IMAGE).
                append(SLASH).
                append(prefix).
                append(SLASH).
                append(new SimpleDateFormat(FORMAT).format(new Date())).
                append(id).
                append(".").
                append(fileName.substring(fileName.lastIndexOf(".") + 1));
        OSSClientUtils.uploadObject2OSS(file, path.toString());

        Picture picture = new Picture();

        Long timestamp = System.currentTimeMillis() / 1000;
        picture.setId(id);
        picture.setOriginalName(fileName);
        picture.setPath(path.toString());
        picture.setCreateAt(timestamp);
        picture.setModifyAt(timestamp);
        picture.setStatus(Picture.CREATE);

        insert(picture);

        return path.toString();
    }

    @Override
    public String uploadToTmp(MultipartFile file, String module) {
        String id = IdWorker.getIdStr();
        String prefix = getPrefixFromCache(module);
        String fileName = file.getOriginalFilename();
        StringBuilder path = new StringBuilder().append(prefix).
                append(new SimpleDateFormat(FORMAT).format(new Date())).
                append(id).
                append(fileName.substring(fileName.lastIndexOf(".")));

        File dest = new File(tempPath + path);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        try {
            file.transferTo(dest);
        } catch (IOException e) {
            throw new DataException("File transfer error", e);
        }

        Picture picture = new Picture();
        Long timestamp = System.currentTimeMillis() / 1000;
        picture.setId(id);
        picture.setOriginalName(fileName);
        picture.setPath(path.toString());
        picture.setCreateAt(timestamp);
        picture.setModifyAt(timestamp);
        picture.setStatus(Picture.TEMP);

        insert(picture);

        return fileHost + path;
    }
//
//    @Override
//    public int tmpToOSS(String[] paths) {
//        int i = 0;
//        for (String path : paths) {
//
//            for (int a = 0; a < 3; a++) {
//                try {
//                    OSSClientUtils.uploadObject2OSS(new File(tempPath + path), path);
//                    updateByPath(path);
//                    break;
//                } catch (Exception e) {
//                    if (a == 2) {
//                        FileUtils.copySingleFileTo(tempPath + path, exceptionPath);
//                    }
//                }
//            }
//
//            i++;
//        }
//
//        return i;
//    }

    @Override
    public int tmpToOSSs(String[] paths) {
        final AtomicInteger i = new AtomicInteger(0);
        Arrays.asList(paths).parallelStream().map(path -> {
            try {
                OSSClientUtils.uploadObject2OSS(new File(tempPath + path), path);
                updateByPath(path);
                //break;
            } catch (Exception e) {
                for (int a = 0; a < 2; a++) {
//                    if (a == 2) {
                    FileUtils.copySingleFileTo(tempPath + path, exceptionPath);
//                    }
                }
            }
            i.incrementAndGet();
            return null;
        });
//                try {
//                    OSSClientUtils.uploadObject2OSS(new File(tempPath + path), path);
//                    updateByPath(path);
//                    //break;
//                } catch (Exception e) {
//                    for (int a = 0; a < 2; a++) {
////                    if (a == 2) {
//                        FileUtils.copySingleFileTo(tempPath + path, exceptionPath);
////                    }
//                }
//            }
        // i++;
    }

    //return i;
}

    @Override
    public boolean delete(String path) {
        boolean delete = OSSClientUtils.deleteObject(path);
        if (delete) {
            Picture query = new Picture();
            query.setPath(path);
            int i = baseMapper.delete(new QueryWrapper<>(query));

            if (i != 1) {
                logger.error("picture delete error! entity:{}", query);
            }
        }
        return delete;
    }

    @Override
    public void tempFileClean() {
        List<String> prefixAll = pictureConfigService.getPrefixAll();

        if (prefixAll == null || prefixAll.isEmpty()) {
            logger.warn("picture config is empty");
            return;
        }

        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -7);
        String datePath = new SimpleDateFormat(FORMAT).format(calendar.getTime());

        for (String prefix : prefixAll) {
            logger.info("delete folder ", tempPath + prefix + datePath);
            FileUtils.delFolder(tempPath + prefix + datePath);
        }
    }

    private int insert(Picture entity) {
        int insert = baseMapper.insert(entity);

        if (insert != 1) {
            logger.error("picture insert error! entity:", entity);
        }
        return insert;
    }

    private int updateByPath(String path) {
        int beginIndex = path.lastIndexOf("/") + 1;
        int endIndex = path.lastIndexOf(".");

        Picture picture = new Picture();
        picture.setId(path.substring(beginIndex, endIndex));
        picture.setModifyAt(System.currentTimeMillis() / 1000);
        picture.setStatus(Picture.CREATE);

        return baseMapper.updateById(picture);

    }

}
